//
// Created by benxb on 2021/11/27.
//

#include "mem/tuple.h"
#include "common/logger.h"

namespace benxdb {

void Tuple::GetValue(const Column &column, Value& val) const {
    if (column.GetBytesOffset() + column.GetLength() > size_) {
        LOG_ERROR("Wrong column when get value from tuple.");
    }
    val = Value(column.GetType(), values_+column.GetBytesOffset());
}

Tuple::Tuple(const std::vector<Value>& values) {
    uint32_t allocate_size = 0;
    for (const auto& v : values) {
        allocate_size += v.GetLength();
    }
    values_ = new char[allocate_size];
    uint32_t offset = 0;
    for (const auto& v : values) {
        memcpy(values_ + offset, v.GetData(), v.GetLength());
        offset += v.GetLength();
    }
    size_ = offset;
}

Tuple::Tuple(record_id_t rid, const std::vector<Value>& values): record_id_(rid) {
    new (this) Tuple(values);
}

Tuple::Tuple(uint32_t size) {
    size_ = size;
    values_ = new char[size];
}

void Tuple::AppendValue(const Column& column, const Value& val){
    if (column.GetBytesOffset() + column.GetLength() > size_) {
        LOG_ERROR("Wrong column when get value from tuple.");
    }
    memcpy(values_ + column.GetBytesOffset(), val.GetData(), column.GetLength());
}

void Tuple::AppendData(const Column &column, char *data) {
    if (column.GetBytesOffset() + column.GetLength() > size_) {
        LOG_ERROR("Wrong column when get value from tuple.");
    }
    memcpy(values_ + column.GetBytesOffset(), data, column.GetLength());
}

Tuple::Tuple(char *data, u_int32_t size) {
    memcpy(values_, data, size);
    size_ = size;
}

Tuple::~Tuple() {
    delete[] values_;
    values_ = nullptr;
}

void Tuple::ReadData(std::iostream& io) {
    io.read(values_, size_);
}

Tuple::Tuple(std::iostream &io, uint32_t size) : size_(size) {
    values_ = new char[size];
    io.read(values_, size_);
}

Tuple::Tuple(Tuple &&other) noexcept {
    values_ = other.values_;
    other.values_ = nullptr;
    size_ = other.size_;
    record_id_ = other.record_id_;
}

Tuple::Tuple(const Tuple &other) {
    values_ = new char[other.size_];
    size_ = other.size_;
    record_id_ = other.record_id_;
    memcpy(values_, other.values_, size_);
}

}
